package com.tilaiedu.mvc.controller;

import com.tilaiedu.mvc.common.R;
import com.tilaiedu.mvc.entity.Goods;
import com.tilaiedu.mvc.service.GoodsService;
import com.tilaiedu.mvc.vo.PageVO;
import com.tilaiedu.mvc.vo.SearchVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Map;
import java.util.UUID;

/**
 * @Author xlzhang
 * @Date 2022/5/26 11:20
 * @Version 1.0
 * @Description TODO
 */
@Slf4j
// @Controller
@RestController
public class GoodsController {

    @Autowired
    private GoodsService goodsService;


    // 表示在前后端分离开发时可以跨域请求
    // @CrossOrigin
    @GetMapping("/products")
    public R<PageVO<Goods>> findAllGoods(SearchVO searchVO,
                          @RequestParam(value = "page",defaultValue = "1") Integer page,
                          @RequestParam(value = "limit",defaultValue = "5") Integer limit){
        int a= 10/0;
        log.debug("searchVO={}",searchVO);
        log.debug("page={}",page);
        // 查询数据库
        PageVO<Goods> pageVO = goodsService.selectAllWithParam(searchVO, page, limit);
        // 将对象保存到session中
        //session.setAttribute("pageVO",pageVO);
        log.debug("{}",pageVO);
        return R.ok(pageVO);
    }

    @Value("${fileUpload.server.url}")
    private String fileServerUrl;
    /**
     * 添加商品
     * @param goods
     * @return
     * @throws IOException
     */
    @PostMapping("/product")
    // 注意，这里可以使用map批量接收除图片以外的所有参数
    //当使用多部分上传中有json时，也是使用@RequestPart 来解析数据，代替了@RequestBody
    public R<String> addGoods(@RequestPart Map<String,Object> goods,
                           @RequestPart MultipartFile gimg) throws IOException {
        //获取文件服务器地址
        // 常规情况下，图片一般都是保存在一个专门的文件服务器上  SSO
        File folder = new File(fileServerUrl);
        if (!folder.exists()) {
            boolean mkdirs = folder.mkdirs();
        }
        //获取文件名称
        String oldName = gimg.getOriginalFilename();
        log.debug("--> 当前上传文件原名称:{}",oldName);

        // 判断当前是否有上传文件，如果有才保存图片并添加路径到数据库
        if (StringUtils.hasText(oldName)) {
            // 处理文件名称，让当前的文件不会产生文件名冲突，加一个唯一的uuid
            // UUID是jdk准备的一个生成全世界唯一32位字符串的一个工具类
            String newName = UUID.randomUUID() + "" + System.currentTimeMillis() + oldName;
            // 保存文件到指定的位置
            // d:/fileUpload/a5ab26fc-2528-45da-9f20-337465166c0c165361915184309a92e670240180c9d86f82f891b8b17.jpeg
            gimg.transferTo(new File(folder, newName));
            // 处理保存到数据库的文件路径,这里要跟图片下载的资源路径匹配
            String saveDBPath = "fileDir/" + newName;
            // 将图片的路径写入商品信息map中.一起保存到数据库
            goods.put("gimg", saveDBPath);
            log.debug("--> 商品图片地址:{}",saveDBPath);
        }

        // 保存数据到数据库
        int res = goodsService.addGoods(goods);
        log.debug(res>0?"--> 添加成功":"-- >添加失败");
        // 跳转重新查询数据显示
        return R.ok("添加商品成功");
    }

    /**
     * 修改(更新)
     * @param goods
     * @param gimg
     * @return
     * @throws IOException
     */
    @PutMapping("/product")
    public R<String> updateGoods(@RequestPart Map<String,Object> goods,
                              @RequestPart MultipartFile gimg) throws IOException {
        log.debug("更新图片：{}",gimg.getOriginalFilename());
        log.debug("更新数据：{}",goods);

        File folder = new File(fileServerUrl);
        if (!folder.exists()) {
            folder.mkdirs();
        }
        // 获取文件名称
        String oldName = gimg.getOriginalFilename();
        // 判断当前是否有上传文件，如果有才保存图片并添加路径到数据库
        if (StringUtils.hasText(oldName)) {
            String newName = UUID.randomUUID() + oldName;
            // 保存文件
            gimg.transferTo(new File(folder, newName));
            // 处理保存到数据库的文件路径
            String saveDBPath = "fileDir/" + newName;
            goods.put("gimg", saveDBPath);
        }
        // 保存数据到数据库
        int res = goodsService.updateByGidWithMap(goods);

        log.debug(res>0?"修改成功":"添加失败");
        // 跳转重新查询数据显示
        return R.ok("修改成功");
    }

    // 	http://localhost:8080/ssm/fileDir/a5ab26fc-2528-45da-9f20-337465166c0c165361915184309a92e670240180c9d86f82f891b8b17.jpeg
    // 图片下载的功能
    @GetMapping("/fileDir/{fileName}")
    public ResponseEntity<byte[]> fileDownload(@PathVariable String fileName) throws IOException {
        // 根据请求传入的文件名称拼接文件全路径
        // String filePath = FILE_SERVER_URL + imgName;
        File filePath = new File(fileServerUrl, fileName);
        // 1.读取文件(响应体)
        FileInputStream inputStream = new FileInputStream(filePath);
        byte[] buff = new byte[inputStream.available()];
        int read = inputStream.read(buff);
        // 关闭流对象
        inputStream.close();

        // 2.设置响应行
        HttpStatus httpStatus = HttpStatus.OK;

        // 3.设置响应头
        HttpHeaders headers = new HttpHeaders();
        // 设置媒体类型,以二进制流的方式响应数据
        //response.setContentType("application/octet-stream");
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        // 设置内容的打开方式为附件模式
        // response.addHeader("Content-Disposition", "attachment;filename="+fileName);
        // headers.add("Content-Disposition", "attachment;filename="+fileName);
        headers.setContentDispositionFormData("attachment",fileName);
        // 配置响应对象，以统一格式响应数据
        return new ResponseEntity<>(buff, headers, httpStatus);
    }

    /**
     * 删除
     * @param gid
     * @return
     */
    @DeleteMapping("/product/{gid}")
    public R<String> deleteGoods(@PathVariable Integer gid){
        int res = goodsService.deleteGoodsByID(gid);
        log.debug(res>0?"--> 删除成功":"-- >删除失败");
        // 跳转重新查询数据显示
        return R.ok("删除成功");
    }
}
